package controller

import (
	"bookmark-web/dao"
	"bookmark-web/logic"
	"bookmark-web/models"
	"bookmark-web/utils"
	"log"
	"strconv"

	"github.com/gin-gonic/gin"
)

// SetupCategoryRouter 设置分类相关路由
func SetupCategoryRouter(api *gin.RouterGroup) {
	category := api.Group("/category")
	{
		category.POST("/", CreateCategory)                         // 创建分类
		category.GET("/:id", GetCategory)                          // 获取单个分类
		category.GET("/", GetCategoriesList)                       // 获取分类列表（分页）
		category.GET("/tree", GetCategoryTree)                     // 获取分类树
		category.PUT("/:id", UpdateCategory)                       // 更新分类
		category.DELETE("/:id", DeleteCategory)                    // 删除分类
		category.GET("/check-children/:id", CheckCategoryChildren) // 检查分类是否有子分类
		category.GET("/search", SearchCategories)                  // 搜索分类
	}
}

// CreateCategory 创建分类控制器
// @Summary 创建分类
// @Description 创建新的分类
// @Tags 分类相关
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param data body models.Category.CategoryCreateRequest true "分类信息"
// @Success 200 {object} utils.Response "创建成功"
// @Router /category [post]
func CreateCategory(c *gin.Context) {
	// 1. 获取用户ID，从认证中间件中获取
	userID := getUserID(c)

	// 2. 绑定请求参数
	var req models.CategoryCreateRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		log.Printf("参数绑定失败: %v", err)
		utils.InvalidParams(c, "请求参数格式错误")
		return
	}

	// 3. 调用业务逻辑层创建分类
	categoryResp, err := logic.CreateCategory(&req, userID)
	if err != nil {
		log.Printf("创建分类失败: %v", err)
		utils.Error(c, err.Error())
		return
	}

	// 4. 返回成功响应
	utils.Success(c, "创建分类成功", categoryResp)
}

// GetCategory 获取单个分类控制器
// @Summary 获取单个分类
// @Description 根据ID获取单个分类
// @Tags 分类相关
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param id path string true "分类ID"
// @Success 200 {object} utils.Response "获取成功"
// @Router /category/{id} [get]
func GetCategory(c *gin.Context) {
	// 1. 获取用户ID
	userID := getUserID(c)

	// 2. 获取分类ID
	idStr := c.Param("id")
	// 将字符串转换为 uint，同时检查非法参数
	id, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		utils.InvalidParams(c, "分类ID格式错误")
		return
	}

	// 3. 调用业务逻辑层获取分类
	categoryResp, err := logic.GetCategoryByID(uint(id), userID)
	if err != nil {
		log.Printf("获取分类失败: %v", err)
		utils.Error(c, err.Error())
		return
	}

	// 4. 返回成功响应
	utils.Success(c, "获取分类成功", categoryResp)
}

// GetCategoriesList 获取分类列表控制器（分页）
// @Summary 获取分类列表
// @Description 获取分类列表（分页）
// @Tags 分类相关
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param page query int false "页码"
// @Param page_size query int false "每页数量"
// @Success 200 {object} utils.Response "获取成功"
// @Router /category [get]
func GetCategoriesList(c *gin.Context) {
	// 1. 获取用户ID
	userID := getUserID(c)

	// 2. 绑定查询参数
	var req models.CategoryQueryRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		log.Printf("参数绑定失败: %v", err)
		utils.InvalidParams(c, "请求参数格式错误")
		return
	}

	// 3. 调用业务逻辑层获取分类列表
	listResp, err := logic.GetCategoriesList(userID, &req)
	if err != nil {
		log.Printf("获取分类列表失败: %v", err)
		utils.Error(c, err.Error())
		return
	}

	// 4. 返回成功响应
	utils.Success(c, "获取分类列表成功", listResp)
}

// GetCategoryTree 获取分类树控制器
// @Summary 获取分类树
// @Description 获取分类的树形结构
// @Tags 分类相关
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Success 200 {object} utils.Response "获取成功"
// @Router /category/tree [get]
func GetCategoryTree(c *gin.Context) {
	// 1. 获取用户ID
	userID := getUserID(c)

	// 2. 调用业务逻辑层获取分类树
	treeResp, err := logic.GetCategoryTree(userID)
	if err != nil {
		log.Printf("获取分类树失败: %v", err)
		utils.Error(c, err.Error())
		return
	}

	// 3. 返回成功响应
	utils.Success(c, "获取分类树成功", treeResp)
}

// UpdateCategory 更新分类控制器
// @Summary 更新分类
// @Description 更新分类信息
// @Tags 分类相关
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param id path string true "分类ID"
// @Param data body models.Category.CategoryUpdateRequest true "分类信息"
// @Success 200 {object} utils.Response "更新成功"
// @Router /category/{id} [put]
func UpdateCategory(c *gin.Context) {
	// 1. 获取用户ID
	userID := getUserID(c)

	// 2. 获取分类ID
	idStr := c.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		utils.InvalidParams(c, "分类ID格式错误")
		return
	}

	// 3. 绑定请求参数
	var req models.CategoryUpdateRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		log.Printf("参数绑定失败: %v", err)
		utils.InvalidParams(c, "请求参数格式错误")
		return
	}

	// 4. 获取父分类ID，如果没有指定则为0（顶级分类）。没选择父类即将待修改分类修改为父分类
	parentId := uint(0)
	if req.ParentID != nil {
		parentId = *req.ParentID
	}

	log.Printf("更新分类请求 - 分类ID: %d, 新名称: %s, 目标父分类ID: %d", id, req.Name, parentId)

	// 5. 调用业务逻辑层更新分类
	categoryResp, err := logic.UpdateCategory(uint(id), &req, userID, parentId)
	if err != nil {
		log.Printf("更新分类失败: %v", err)
		utils.Error(c, err.Error())
		return
	}

	// 5. 返回成功响应
	utils.Success(c, "更新分类成功", categoryResp)
}

// DeleteCategory 删除分类控制器
// @Summary 删除分类
// @Description 删除分类
// @Tags 分类相关
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param id path string true "分类ID"
// @Success 200 {object} utils.Response "删除成功"
// @Router /category/{id} [delete]
func DeleteCategory(c *gin.Context) {
	// 1. 获取用户ID
	userID := getUserID(c)

	// 2. 获取分类ID
	idStr := c.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		utils.InvalidParams(c, "分类ID格式错误")
		return
	}

	// 3. 调用业务逻辑层删除分类
	err = logic.DeleteCategory(uint(id), userID)
	if err != nil {
		log.Printf("删除分类失败: %v", err)
		utils.Error(c, err.Error())
		return
	}

	// 4. 返回成功响应
	utils.Success(c, "删除分类成功", nil)
}

// CheckCategoryChildren 检查分类是否有子分类控制器
// @Summary 检查分类是否有子分类
// @Description 检查指定分类是否包含子分类
// @Tags 分类相关
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param id path string true "分类ID"
// @Success 200 {object} utils.Response "检查成功"
// @Router /category/check-children/{id} [get]
func CheckCategoryChildren(c *gin.Context) {
	// 1. 获取用户ID
	userID := getUserID(c)

	// 2. 获取分类ID
	idStr := c.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		utils.InvalidParams(c, "分类ID格式错误")
		return
	}

	// 3. 检查分类下是否有子分类
	hasChildren, err := dao.CheckCategoryChildrenExists(uint(id), userID)
	if err != nil {
		log.Printf("检查子分类失败: %v", err)
		utils.Error(c, "检查子分类失败")
		return
	}

	// 4. 返回结果
	response := map[string]interface{}{
		"has_children": hasChildren,
	}
	utils.Success(c, "检查成功", response)
}

// SearchCategories 搜索分类控制器
// @Summary 搜索分类
// @Description 根据关键词搜索分类
// @Tags 分类相关
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param keyword query string true "搜索关键词"
// @Param page query int false "页码"
// @Param page_size query int false "每页数量"
// @Success 200 {object} utils.Response "搜索成功"
// @Router /category/search [get]
func SearchCategories(c *gin.Context) {
	// 1. 获取用户ID
	userID := getUserID(c)

	// 2. 获取搜索参数
	keyword := c.Query("keyword")
	if keyword == "" {
		utils.InvalidParams(c, "搜索关键词不能为空")
		return
	}

	// 3. 获取分页参数
	page := 1
	pageSize := 10

	if pageStr := c.Query("page"); pageStr != "" {
		if p, err := strconv.Atoi(pageStr); err == nil && p > 0 {
			page = p
		}
	}

	if sizeStr := c.Query("page_size"); sizeStr != "" {
		if s, err := strconv.Atoi(sizeStr); err == nil && s > 0 {
			pageSize = s
		}
	}

	// 4. 调用业务逻辑层搜索分类
	listResp, err := logic.SearchCategories(userID, keyword, page, pageSize)
	if err != nil {
		log.Printf("搜索分类失败: %v", err)
		utils.Error(c, err.Error())
		return
	}

	// 5. 返回成功响应
	utils.Success(c, "搜索分类成功", listResp)
}

// CategoryPage 分类管理页面
func CategoryPage(c *gin.Context) {
	c.HTML(200, "category.html", gin.H{
		"title": "分类管理",
	})
}
